package com.zsk.okhttp;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import com.alibaba.fastjson.JSON;

import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;

/**
 * form-data/application-json/query params post task
 * @author keke
 * @date 2020/09/10
 */
public class PostTask implements IPostTask {

    protected OkHttpClient client;

    protected final static MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
    protected final static MediaType FORM_TYPE = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");

    protected Map<String, Object> jsonMap;
    protected String bodyStr;
    protected FormBody.Builder formBodyBuilder;
    protected Request.Builder requestBuilder;
    protected HttpUrl.Builder urlBuilder;
    protected MediaType mediaType;

    public PostTask(OkHttpClient client, String url) {
        super();
        this.client = client;
        this.requestBuilder = new Request.Builder();
        this.urlBuilder = HttpUrl.parse(url).newBuilder();
    }

    @Override
    public ResData run() throws IOException {
        Request request = createRequest();
        return ResData.of(client.newCall(request).execute());
    }

    @Override
    public void run(Callback callback) {
        Request request = createRequest();
        client.newCall(request).enqueue(callback);
    }

    @Override
    public IPostTask addHeader(String name, String value) {
        requestBuilder.addHeader(name, value);
        return this;
    }

    @Override
    public IPostTask addFormData(String name, String value) {
        if (formBodyBuilder == null) {
            formBodyBuilder = new FormBody.Builder();
        }
        formBodyBuilder.add(name, value);
        return this;
    }

    @Override
    public IPostTask addJson(String name, Object value) {
        if (jsonMap == null) {
            jsonMap = new HashMap<>(16);
        }
        jsonMap.put(name, value);
        return this;
    }

    @Override
    public IPostTask addBody(String body) {
        bodyStr = body;
        return this;
    }

    @Override
    public IPostTask addBody(MediaType type, String body) {
        Optional.ofNullable(type).ifPresent(t -> mediaType = t);
        System.out.println(mediaType);
        bodyStr = body;
        return this;
    }

    /**
     * if bodyStr and jsonMap exist at the same time, bodyStr is used at first
     * 
     * @return
     */
    protected Request createRequest() {
        requestBuilder.url(urlBuilder.build());
        if (formBodyBuilder != null) {
            requestBuilder.post(formBodyBuilder.build());
        } else {
            // json request
            if (bodyStr != null && !bodyStr.isEmpty()) {
                mediaType = Optional.ofNullable(mediaType).orElse(JSON_TYPE);
                requestBuilder.post(RequestBody.create(mediaType, bodyStr));
            } else if (jsonMap != null && jsonMap.size() > 0) {
                requestBuilder.post(RequestBody.create(JSON_TYPE, JSON.toJSONString(jsonMap)));
            } else {
                requestBuilder.post(RequestBody.create(FORM_TYPE, ""));
            }

        }

        Request request = requestBuilder.build();
        return request;
    }

    @Override
    public IPostTask addQueryParam(String name, String value) {
        urlBuilder.addQueryParameter(name, value);
        return this;
    }

}
